DDSキットをパソコンからコントロールしてみよう!



<項目>接続回路について
DDS基板にあるシリアル入力の(1)STB、(2)DATA、(3)SCKの各端子は、表1に示すようにPIC16F877のREポート側に接続しました。PIC16F877のREポートは、ちょうどポートが3つあるので、ここのポートを選びました。REポートでなければならないという理由は特にありません。

表1.DDSとPICの接続関係
DDS側のシリアル
入力端子
PIC16F877側の
接続ポート
STB RE0
DATA RE1
SCK RE2

図1に、概略接続図を示します。PICリセット後、確認のため PORTB の LED が1秒間点灯するようにLEDを接続しています。RS232C関連の周辺回路は、RC7,RC6ポートに接続します。詳細はシリアル通信の項目を参照してください。

DDS制御回路の概略接続図
図1.DDS制御回路の概略接続図


<項目>DDS制御プログラム(2)

図2にDDSの制御プログラムのフローチャートを示します。プログラムの解説については、「プログラムの説明(2)」の項をご参照ください。リセット後、PICが動作していることを簡単に確認するため、PORTBに接続されたLEDが1秒間点灯します。DSSの設定ですが、 パソコンから次の4つの設定データをRS232Cでシリアル送信します。

  1. チップセレクト&コマンドデータ
  2. 周波数データ(Lower Byte: 0ビット目〜7ビット目)
  3. 周波数データ(Middle Byte: 8ビット目〜15ビット目)
  4. 周波数データ(Higher Byte: 16ビット目〜23ビット目)

コマンドデータ4ビットと、チップセレクトデータ3ビット分は、次のようにまとめて送ります。
(例)チップセレクト(CS2=「H」、CS1=「H」、CS0=「H」)「111」で、コマンドC「1100」としたとき、
「コマンドデータ」と「チップセレクトデータ」をまとめて、「1100111」とします。すなわち、67になります。

次に周波数データは、次のように3つに分割して送ります。
(例)f=10MHzの周波数に設定する場合、16進表記で考えると
10M=10000000→989680 となります。
ここで、80が周波数データ(Lower Byte)に相当、96が周波数データ(Middle Byte)に相当、98が周波数データ(Higher Byte)に相当します。

以上の例から、チップセレクト(CS2=「H」、CS1=「H」、CS0=「H」)に設定されたDDSキットを、f=10MHzの周波数で、コマンドC(DSS メモリ 1CH に周波数データを書き込み、これを出力する)という場合は、順に67H,80H,96H,98Hの4つのデータを送信します。
シリアル送信されたデータはPIC側で一度バッファに格納された後、DDSへ設定データを送ります。なお、設定完了後も受信動作を続けますので、パソコン側で各種コマンドや周波数を新たに設定することも可能です。


DDS制御プログラムのフローチャート
DDS制御プログラムのフローチャート
DDS制御プログラムのフローチャート

図2.DDS制御プログラムのフローチャート

(注)以下に示すプログラムには、ホームページ画面作成の都合上、空白として全角文字のスペースなどが挿入されています。したがって、下記プログラムリストをそのままコピーしてMPLABのソースファイルとされた場合には、エラーとなることがあります。

→ここをクリックして、下記のプログラムをダウンロードするようにしてください。
  <ダウンロードする>ファイル名:「dds_2.asm」 サイズ7.81kバイト

→ここをクリックして、下記のオブジェクトファイルをダウンロードするようにしてください。
  <ダウンロードする>ファイル名:「dds_2.hex」 サイズ717バイト

;***********************************************************
; DDSコントロール・プログラム2
;
;【 動作内容 】
;  PICリセット後、確認のため PORTB の LED が1秒間点灯する。
;  パソコンからチップセレクト・コマンドデータ、及び
;  周波数データを、RS232C シリアル通信で送る。
;  周波数データは、Lower Byte、Middle Byte、Higher Byte
;  の順に、それぞれ 3分割した値を送る。
;  各データはバッファに一時格納し、データの受信が完了したら、
;  随時、DDS 設定信号を出力する。
;
;【 DDS 接続ポート 】
;  (DDS)   (PIC)
;   STB ………RE0
;   DATA………RE1
;   SCK ………RE2
;
;【 RS-232C 接続ポート 】
;  非同期式通信モード
;  ボーレート 9600bps
;  8ビット・ノンパリティ
;  割り込みは使用しない
;
;***********************************************************
    LIST   P=PIC16F877
    INCLUDE  P16F877.INC
;(1)プロセッサの種別指定
;(2)インクルードファイルの指定
;***********************************************************
; 変数定義とレジスタ割付
;***********************************************************
COUNT   EQU  20H
COUNT1  EQU  21H
COUNT2  EQU  22H
COUNT3  EQU  23H
COUNT4  EQU  24H

TEMP    EQU  25H
COUNT_D  EQU  26H
COUNT_S  EQU  27H

;(3)ループカウンタ
;   ループカウンタ1
;   ループカウンタ2
;   ループカウンタ3
;   ループカウンタ4

;   一時保管データ
;   データカウンタ
;   シフトカウンタ

;***********************************************************
; 初期化
; (注)バンクの位置に注意
;***********************************************************
    ORG   0
    BSF   STATUS,RP0
    MOVLW  B'00000010'
    MOVWF  ADCON1
    CLRF  TRISE
    CLRF  TRISB
    MOVLW  B'10111111'
    MOVWF  TRISC
    MOVLW  B'00100100'
    MOVWF  TXSTA
    MOVLW  81H
    MOVWF  SPBRG
    BCF   STATUS,RP0
    MOVLW  B'10010000'
    MOVWF  RCSTA

;(4)プログラムの開始番地の指定
;(5)Bank 1 へ切替
;(6)RE0,RE1,RE2 デジタル入出力
;   ADCON1レジスタの設定
;(7)PORTE 全ポートを出力に設定
;(8)PORTB 全ポートを出力に設定
;(9)RC7/RX(入力),RC6/TX(出力)
;(10)PORTC の設定
;(11)8BIT,送信許可,非同期,高速
;   TXSTA レジスタの設定
;(12)ボーレート 9600bps (20MHz:高速設定時)
;   SPBRG レジスタの設定
;(13)Bank 0 へ戻す
;(14)シリアル,8BIT,継続受信許可
;   RCSTA レジスタの設定

;***********************************************************
; メインプログラム
;***********************************************************

    MOVLW  B'00000111'
    MOVWF  PORTE
MAIN
    BSF   STATUS,IRP
    MOVLW  0A0H
    MOVWF  FSR
    MOVLW  4H
    MOVWF  COUNT_D

;(15)DDS信号ラインのレベルの初期設定
;   SCK,DATA,STB = [H],[H],[H] に設定
;   PORTEへ出力(DDSとの通信の初期設定)

;(16)間接アドレス設定
;   バッファの先頭アドレスをセットする
;   間接アドレスポインタの初期化
;(17)4回繰り返す(DDS設定データ)
;   データカウンタのセット


    MOVLW  B'11111111'
    MOVWF  PORTB
    CALL  TIME1S
    MOVLW  B'00000000'
    MOVWF  PORTB

;(18)データ受信待ちになっていることを確認するためのLED表示
;   11111111 を Wreg にロードする
;   PORTBへWregのデータを出力(LEDの点灯)
;(19)1秒のウエイトを入れる
;(20)00000000 を Wreg にロードする
;    PORTBへWregのデータを出力(LEDの消灯)


LPRCV
    BTFSS  PIR1,RCIF
    GOTO  LPRCV




;(21)USART 受信割り込みフラグビットのチェック
;   PIR1 レジスタの RCIF が「0」だったら
;   LPRCV ラベル間をループする


    BTFSC  RCSTA,FERR
    GOTO  FRAME

    BTFSC  RCSTA,OERR
    GOTO  OVER

; ****** エラーチェック ******
;(22)フレーミングエラーのチェック(1:エラー,0:正常)
;   フレーミングエラー時 FRAME のラベルへジャンプする
;
;(23)オーバーランエラーのチェック(1:エラー,0:正常)
;   オーバーランエラー時 OVER のラベルへジャンプする


    MOVF  RCREG,W
    MOVWF  INDF
    INCF  FSR,F
    DECFSZ COUNT_D,F
    GOTO  LPRCV
    MOVLW  0
    MOVWF  INDF

; ****** 受信データの格納 ******
;(24)RCREGレジスタから受信データを読み込む
;(25)バッファに格納
;(26)ポインタ +1
;(27)データカウンタ −1
;   LPRCV のラベルへ戻り繰り返す
;(28)25,24ビット目のDDS周波数データ(常に0)
;   バッファに格納

DDS
    MOVLW  0A0H
    MOVWF  FSR
    MOVLW  5H
    MOVWF  COUNT_D

; ****** 格納データの取りだし ******
;(29)バッファの先頭アドレスをセットする
;   間接アドレスポインタをリセットする
;(30)5回繰り返す(DDS設定データ)
;   データカウンタのセット

DDS_SET
    MOVF  INDF,W
    MOVWF  TEMP
    MOVF  COUNT_D,W
    CALL  TABLE
    MOVWF  COUNT_S


;(31)バッファに格納されているデータをWregにロードする
;   一時保管データへ
;(32)データカウンタの値をWregへロードする(OFFSET)
;(33)シフトカウンタ値の読み込みサブルーチンへ
;(34)シフトカウンタのセット

DDS_LP
    RRF   TEMP,F
    BTFSS  STATUS,C
    GOTO  DATA_L
    GOTO  DATA_H


;(35)DDS設定データを取り出す。
;(36)データが1だったら次の命令をスキップ
;   DATA = [L]
;   DATA = [H]

SET_SCK
    BCF   PORTE,2
    NOP
    BSF   PORTE,2
    DECFSZ COUNT_S,F
    GOTO  DDS_LP
    INCF  FSR,F
    DECFSZ COUNT_D,F
    GOTO  DDS_SET

;(37)SCK = [L]
;(38)ポートの誤動作防止
;(39)SCK = [H]
;(40)シフトカウンタ −1
;   DDS_LP のラベルへ戻り繰り返す
;(41)間接アドレスポインタ +1
;(42)データカウンタ −1
;   DDS_SET のラベルへ戻り繰り返す

    BSF   PORTE,1
    NOP
    BCF   PORTE,0
    NOP
    BSF   PORTE,0

    GOTO  MAIN

;(43)DATA = [H]
;(44)ポートの誤動作防止
;(45)STB = [L]
;(46)ポートの誤動作防止
;(47)STB = [H]

;(48)繰り返しデータ受信動作に入る

DATA_L
    BCF   PORTE,1
    GOTO  SET_SCK
DATA_H
    BSF   PORTE,1
    GOTO  SET_SCK



;(49)DATA = [L]


;(50)DATA = [H]


;***********************************************************
; シフトカウンタ・テーブル
;***********************************************************
TABLE
    ADDWF  PCL,F
    NOP
    DT    2,8,8,8,7

;(51)TABLEの定義(PC+OFFSET相当のシフトカウンタ値を持って戻る)
;   PC+OFFSET
;(52)ダミーデータ
;(53)各データに対するシフトカウンタ値

;***********************************************************
; RS232Cシリアル通信エラー時の処理
;***********************************************************
FRAME
    MOVLW  B'00001111'
    MOVWF  PORTB
    CALL  TIME1S
    MOVLW  B'00000000'
    MOVWF  PORTB
    MOVF  RCREG,W
    BTFSS  RCSTA,OERR
    GOTO  MAIN
; <フレーミングエラー時の処理>
;(54)00001111 を Wreg にロードする
;   PORTBへWregのデータを出力(LEDの点灯状態でエラーを知らせる)
;(55)1秒のウエイトを入れる
;(56)00000000 を Wreg にロードする
;   PORTBへWregのデータを出力(LEDの消灯)
;(57)ダミーの入力とFERRフラグをリセット(RCREGをリードするとクリア)
;(58)オーバーランエラーのチェック(1:エラー,0:正常)
;   オーバーランエラーがなければ MAIN のラベルへジャンプする

OVER
    MOVLW  B'11110000'
    MOVWF  PORTB
    CALL  TIME1S
    MOVLW  B'00000000'
    MOVWF  PORTB
    BCF   RCSTA,CREN
    BSF   RCSTA,CREN
    GOTO  MAIN


; <オーバーランエラー時の処理>
;(59)11110000 を Wreg にロードする
;   PORTBへWregのデータを出力(LEDの点灯状態でエラーを知らせる)
;(60)1秒のウエイトを入れる
;(61)00000000 を Wreg にロードする
;   PORTBへWregのデータを出力(LEDの消灯)
;(62)OERRのリセット(ビットCREN のクリアによりクリアする)
;(63)連続受信を許可する
;(64)MAIN のラベルへジャンプする

;***********************************************************
;遅延サブルーチン
;***********************************************************
;100μs遅延サブルーチン(20MHzクロック時)
;・・・・・別記プログラムリスト参照・・・・・
;
;10ms遅延サブルーチン(20MHzクロック時)
;・・・・・別記プログラムリスト参照・・・・・
;
;1s遅延サブルーチン(20MHzクロック時)
;・・・・・別記プログラムリスト参照・・・・・

    END
 

【プログラムの説明(2)】ここがポイント
このプログラムについて、順を追って解説を加えておきましょう。

(1)プロセッサの種別指定
定義の仕方は「PROCESSOR」か「LIST」命令を使って設定します。ここで指定するプロセッサ名称は、パッケージの種類を示すサフィックス(最後の英記号の部分)は不要です。

   PROCESSOR  PIC16F877
    または
   LIST  P=PIC16F877

(2)標準ヘッダーファイルのインクルード
標準ヘッダーファイルとは、各プロセッサが持っているSFR(Special Function Register)をラベル(記号)で使える

ため、ラベルとハードウェアの場所とを定義しているファイルです。標準ヘッダーファイルは 「プロセッサ名.INC」というファイル名で統一されて、MPLABのディレクトリに格納されています。従って、これのインクルード方法は下記のようにして行います。
一度、参考までに標準ヘッダーファイルの内容をエディタ等で見ておくことをお勧めします。

   INCLUDE    P16F877.INC
    または
   #INCLUDE   P16F877.INC

(3)変数定義とレジスタ割付
レジスタファイルアドレスを指定するときに、アドレス数値を直接指定することもできますが、数値だけでは間違いも多く、プログラム自身も分かりにくくなってしまいます。そこで、EQU命令などを使ってラベルを設定し変数を定義します。レジスタファイルアドレスは、7ビットあるので、00〜7Fまで最大128個のレジスタが指定できますが、実際に物理的に実装されて汎用的に使用できるレジスタ数はデバイスによって異なっていますので注意が必要です。
PIC16F877の汎用レジスタのアドレスは、20H〜7FH
となっていますので、20H以降のアドレスに割り付けます。

(4)プログラムの開始番地の指定
「ORG」はプログラムの開始番地を指定する擬似命令で、ORG以下の実際のプログラム命令が格納されるプログラムメモリ内の位置(アドレス)を指定します。

   ORG  0  ;0番地から格納することを示します。

コンピュータは一般に電源投入時やリセットをすると必ず0番地からスタートするようになっているので、0番地には必ず命令があることが必要です。

(5)Bank 1 へ切替
PICには各種の動作モードを設定するための Special Register と呼ばれるものが用意されています。PICを動作させるためには、まずこのSpecial Registerの設定から始めます。そしてそれらは全て、Register File と呼ぶメモリとして用意されています。その Register Fileは Bank0, Bank1, Bank2, Bank3 とよばれるアドレス空間をもっているため、多少アクセスの仕方が面倒です。つまりRESET後の通常はBank0となっているので、Bank1側のレジスタにアクセスするときはBankの切替えをしてからとなります。またBank0とBank1に同じ物があるときにはどちらでも同じ様に使えます。
Bank1へ切り替える方法ですが、「STATUS」レジスタにある2ビットのRP0、RP1を変えてBankを指定します。デフォルトは、Bank0です。表2にBankとRP1,RP0ビットとの関係を示します。Bank1へ切り替えるためには、RP0ビットを「1」にします。(RP1はデフォルトで「0」なので変える必要はない。)

 BSF    STATUS,RP0
「STATUS」レジスタのRP0ビットを「1」にする。

表2.BankとRP1,RP0ビットとの関係
Bank RP1 RP0


(6)RE0,RE1,RE2 デジタル入出力
   ADCON1レジスタの設定

ここがポイント
REポートをディジタル入出力ポートとして使用するためには、ADCON1レジスタの設定が必要

REポートをディジタル入出力ポートとして使用するためには、ADCON1レジスタの設定が必要になります。PICのリセット後は、REポートがA/D変換の入力ポートになっているからです。(RAポートも同様)ADCON1レジスタの3〜0ビット(PCFGx)の設定内容より決定します。PCFGx=「0010」 or 「0011」 or 「0100」 or 「0101」 or 「0110」 or 「0111」 or 「1100」 or 「1101」 or 「1110」 or 「1111」のいずれかのときREポートはディジタル入出力ポートになることが分かります。(このとき、RAポートは使用しないので、RAポートの設定は無関係とします)

ADCON1レジスタの設定内容の詳細は、こちらをご覧ください。→ADCON1レジスタの設定内容について

なお、ADCON1レジスタの7〜4ビットは、簡単のためとりあえず「0」とでもしておき、またPCFGx=「0010」とすることで、すなわち、「ADCON1→B’00000010’ (2H)」に設定することで、REポートをディジタル入出力ポートとして使用することができます。

(7)PORTE 全ポートを出力に設定
TRISEレジスタを、CLRF(fレジスタをゼロクリアする命令)で出力設定とします。

 CLRF   TRISE
「TRISEレジスタをゼロクリアする。すなわち、PORTE全ポートを出力に設定する」

(8)PORTB 全ポートを出力に設定
TRISBレジスタを、CLRF(fレジスタをゼロクリアする命令)で出力設定とします。

 CLRF   TRISB
「TRISBレジスタをゼロクリアする。すなわち、PORTB全ポートを出力に設定する」
PORTBにはLEDが接続されており、DDSへシリアル入力する状態に入ったときの確認のために、点灯するようにしています。

(9)RC7/RX(入力),RC6/TX(出力)
シリアル通信の入出力ポートとして、受信入力ポート(RC7/RX)と、送信出力ポート(RC6/TX)を使います。他のRCポートは使いませんので、とりあえず入力に設定しておきます。したがって、RC6のみ出力設定にします。
ということで、B’10111111’ (BFH)をWregにロードする。

(10)PORTC の設定
Wregの内容をTRISCレジスタに上書きする。

(11)8BIT,送信許可,非同期,高速,TXSTA レジスタの設定
「シリアル通信機能」の制御用レジスタの解説項目でTXSTAレジスタを参照してください。

TXSTAレジスタの内容

ということで、TXSTA→B’00100100’ (24H)

(12)ボーレート 9600bps (20MHz:高速設定時), SPBRG レジスタの設定
「シリアル通信機能」のSPBREGレジスタの解説項目で表3.SPBRGの設定値とボーレートを参照してください。ボーレートを9600bpsに設定します。表3−1の低速モードや、表3−2の高速モードがありますが、ここでは高速モードの9600bpsを選択します。クロック周波数が20MHzの場合は、低速モードより高速モードの方がエラーレートが小さいためです。したがって、高速モードの場合のSPBREGは、81Hに設定すればよいことが分かります。
(注)MicroChip社のデータシートは、SPBREGの設定表示は10進数(decimal)になっていますので注意してください。

(13)Bank 0 へ戻す
Bank1での設定が終了した後は、Bank0に戻しておきます。Bank1へ切り替えるためには、RP0ビットを「0」にします。(RP1はデフォルトで「0」なので変える必要はない。)

BCF    STATUS,RP0
「STATUS」レジスタのRP0ビットを「0」にする。すなわち、Bank0に戻す。」


(14)シリアル,8BIT,継続受信許可,RCSTA レジスタの設定
「シリアル通信機能」の制御用レジスタの解説項目でRCSTAレジスタを参照してください。

RCSTAレジスタの内容の決定

ということで、RCSTA→B’10010000’ (90H)

(15)DDS信号ラインのレベルの初期設定
   SCK,DATA,STB = [H],[H],[H] に設定,PORTEへ出力(DDSとの通信の初期設定)

DDSとのシリアル通信を行う前に、信号ライン(SCK,DATA,STB)をすべて「H」に初期設定しておきます。

(16)間接アドレス設定 ここがポイント
バッファの先頭アドレスをセット 間接アドレスポインタの初期化

データメモリのアクセス方法に、直接レジスタのアドレスを指定してアクセスする直接アドレッシングのほかに、間接アドレッシングという方法があります。間接アドレッシングは、FSRレジスタ(File Selection Register)と、STATUSレジスタ中のIRPビットを使います。このFSRレジスタがプログラム中で自由に書き換えられるので、プログラム中にバッファなどを作って連続した領域を順にアクセスするのに便利に使えます。また、間接アドレッシングで指定されたデータメモリは、INDFレジスタを経由して間接的にアクセスします。すなわち、指定したデータメモリに書き込む場合には、INDFレジスタに書き込み、指定したデータメモリの内容を読み出すときには、INDFレジスタの内容を読み込みます。
図3に間接アドレッシングでのデータメモリ・アドレス指定についての解説図を示します。

間接アドレッシングのデータメモリ・アドレス指定について
図3.間接アドレッシングのデータメモリ・アドレス指定について

(プログラム例)Bank3の汎用データメモリのアドレス20Hを指定したいとき
STATUSレジスタのRP0,RP1を使ってBankの切り替えをする必要はありません、次のように直接任意のBankをアクセスします。図2のBank指定から、STATUSレジスタのIRPを「1」、FSRレジスタの7ビット目を「1」にします。
また、場所アドレスの指定からFSRレジスタの6〜0ビット目を、20Hにしますが、7ビット目が「1」になっていますので、FSRレジスタは、A0Hにします。したがって、

BSF     STATUS,IRP  ;STATUSレジスタのIRPビットを「1」にする。
MOVLW   0A0H      ;A0HをWregレジスタにロードする
MOVWF   FSR       ;Wregレジスタの内容をFSRレジスタに格納する。
となります。

(17)4回繰り返す(DDS設定データ),データカウンタのセット
パソコンから RS232C シリアル通信にて、次の1〜4までの各データが順に送られてくるので、受信動作を4回繰り返すようにデータカウンタをセットします。

  1. チップセレクト&コマンドデータ
  2. 周波数データ(Lower Byte: 0ビット目〜7ビット目)
  3. 周波数データ(Middle Byte: 8ビット目〜15ビット目)
  4. 周波数データ(Higher Byte: 16ビット目〜23ビット目)


(18)データ受信待ちになっていることを確認するためのLED表示
    11111111 を Wreg にロードし、PORTBへWregのデータを出力(LEDの全点灯)

ここで、レジスタの初期設定が終了し、パソコンからのデータ入力待ち(受信状態)に入ったことを確認するため、 PORTB の LED を全点灯させるようにします。

(19)1秒のウエイトを入れる
PORTB の LED の点灯時間を1秒間に設定します。ここでは、遅延サブルーチンを使っています。

(20)00000000 を Wreg にロードし、
    PORTBへWregのデータを出力(LEDの消灯)
点灯していたLEDを消灯させ、データの受信状態に入ります。

(21)USART 受信割り込みフラグビットのチェック(1:USART 受信バッファがフル, 0:空)
    受信バッファが空であれば LPRCV のラベル間を繰り返す

周辺機能の割り込みのフラグビットが割り当てられているPIR1レジスタのUSART 受信割り込みフラグビット(RCIF)の状態をチェックします。
USART受信バッファがフルであるとすると、RCIFが「1」となり、次の命令で分岐されます。
BTFSS   PIR1,RCIF
「PIR1」レジスタのRCIFビットが「1」だったら次の命令をスキップし、ループから抜けます。
GOTO   LPRCV
ただし、受信バッファが空の間は、「PIR1」レジスタのRCIFビットが「0」のままですので、LPRCVラベルへ戻ってループを繰り返します。

(22)フレーミングエラーのチェック(1:エラー,0:正常)
受信ステータスおよびコントロールレジスタであるRCSTAレジスタのフレーミングエラービット(FERR)の状態をチェックします。
BTFSC   RCSTA,FERR
「RCSTA」レジスタのFERRビットが正常の「0」だったら次の命令をスキップし、オーバーランエラーのチェックへ進みます。
GOTO   FRAME
フレーミングエラー時 FRAME のラベルへジャンプします。

(23)オーバーランエラーのチェック(1:エラー,0:正常)
受信ステータスおよびコントロールレジスタであるRCSTAレジスタのオーバーランエラービット(OERR)の状態をチェックします。
BTFSC   RCSTA,OERR
「RCSTA」レジスタのOERRビットが正常の「0」だったら次の命令をスキップし、受信データの格納へ進みます。
GOTO   OVER
オーバーランエラー時 OVERのラベルへジャンプします。

(24)RCREGレジスタから受信データを読み込む
RCREGレジスタ(受信データが格納されている)内容をWregへロードする。

(25)バッファに格納
データメモリに書き込む場合には、INDFレジスタを経由して間接的に書き込みます。
MOVWF   INDF
INDFレジスタにWregの内容を格納(→間接アドレッシングで指定したデータメモリに格納される)

(26)ポインタ +1
バッファの間接アドレスポインタを+1にして、次のアドレスを指定します。

(27)データカウンタ −1, LPRCV のラベルへ戻り繰り返す
パソコンから RS232C シリアル通信にて、4Byte分のデータが順に送られてくるので、(17)で4回繰り返すようにセットされたデータカウンタを−1ずつ減らし、0になるまでLPRCV間の受信動作を繰り返します。

(28)24,25ビット目のDDS周波数データ(常に0),バッファに格納
これまでパソコンからは RS232C シリアル通信にて、チップセレクト&コマンドデータ、0ビット目〜23ビット目までの周波数データ(下記に示す1〜4までのデータ)がバッファに格納されました。DDSの周波数データは0ビット〜25ビットで構成されているため、ここで24,25ビット目のDDS周波数データもバッファに格納します。ただし、DDSの設定仕様から24,25ビット目のデータについては、常に0ですので、あえてシリアル通信でこの部分のデータを送る必要はありません。

  1. チップセレクト&コマンドデータ
  2. 周波数データ(Lower Byte: 0ビット目〜7ビット目)
  3. 周波数データ(Middle Byte: 8ビット目〜15ビット目)
  4. 周波数データ(Higher Byte: 16ビット目〜23ビット目)
  5. 周波数データ(24,25ビット目 ビットの値は常に0)


(29)バッファの先頭アドレスをセットする,間接アドレスポインタをリセットする
データの取り出しルーチンに入ったとき、格納されているバッファの先頭に間接アドレスポインタをセットします。
STATUSレジスタのIRPは「1」のまま変化していませんので、あえてセットする必要はありません。FSRの設定を(16)の項目と同じA0Hにセットします。

(30)5回繰り返す(DDS設定データ),データカウンタのセット
(28)でバッファに書き込まれた1〜5までの5つのデータを取り出すため、動作を5回繰り返すようにデータカウンタをセットします。

(31)バッファに格納されているデータをWregにロードする,一時保管データへ
バッファに書き込まれたデータを読み込む場合には、INDFレジスタを経由して間接的に読み込みます。読み込まれたデータは、TEMPレジスタに一時保管しておきます。

(32)データカウンタの値をWregへロードする(OFFSET)
テーブルに記載されているシフトカウンタ値を読み込んでくるため、データカウンタの値をWregにロードします。このデータカウンタの値は、プログラムカウンタにデータカウンタの値(OFFSET分)を足し合わせることで、シフトカウンタ値が記載されたテーブルの位置関係を指し示すようになっています。

(33)シフトカウンタ値の読み込みサブルーチンへ
シフトカウンタ値を読み込むサブルーチンへ飛びます。

(34)シフトカウンタのセット
読み込まれたシフトカウンタの値をセットします。

(35)DDS設定データを取り出す
TEMPレジスタに一時保管されたDDS設定データの内容を、1ビットキャリを含めて右に移動させ、その結果をTEMPレジスタに上書きします。このときTEMPレジスタのLSBのビット(0 or 1)によってCフラグが変化しますので、次の条件分岐で下位から1ビット分ずつDDSの設定データを取り出すことができます。

(36)データが1だったら次の命令をスキップ
   DATA = [L] か DATA = [H] かの条件分岐

1ビット分の読み込まれたデータが、1だったらDDSへのDATA信号ラインを[H]に、0だったらDDSへのDATA信号ラインを[L]にする条件分岐になります。

(37)SCK = [L]
DDSへのSCK信号ラインを[L]にします。

(38)ポートの誤動作防止
ここがポイント
BSF,BCFなどのビット操作命令で、同じポートに出力する場合には、間にダミーとしてNOP命令などを入れる
ここは、(37)と(39)のように、BSF,BCFなどのビット操作命令により同一ポートを続けて設定していると、ポートが誤動作をすることがあるので、ダミーとしてNOPを入れています。BSF,BCFなどのビット操作命令は、一度ポートレジスタのすべてのビットの状態を読み込み、指定ビットのみを変更して再度ポートレジスタに上書きするという操作がされます。すなわち、最初の命令(37)の出力がなされ、次の命令(39)が出力される前に、一度入力動作があるのです。最初の命令の出力と次の命令の入力動作の間は、1クロック分しかなく、20MHzクロックの場合にはわずかに50nsecです。出力ピンの負荷に何らかの容量成分があると、信号の立ち上がりや立ち下がりが遅れるため、最初の命令の出力が完全に落ち着く前に次の命令で読み込みを実行してしまうため誤動作が発生しやすくなります。この対策としては、ビット操作命令で連続して同じポートに出力する場合には、間にNOP命令など他の命令を最低1個挿入するようにします。

(39)SCK = [H]
DDSへのSCK信号ラインを[H]にします。このとき、SCKの立ち上がりでDATAが読み込まれます。

(40)シフトカウンタ −1,DDS_LP のラベルへ戻り繰り返す
シフトカウンタの値を1ずつ減らし、0になるまでDDS_LPとあるラベルへ戻り、DATAの読み込み動作を繰り返します。

(41)間接アドレスポインタ +1
バッファの間接アドレスポインタを+1にして、次のアドレスを指定します。

(42)データカウンタ −1,DDS_SET のラベルへ戻り繰り返す
データカウンタの値を1ずつ減らし、0になるまでDDS_SETとあるラベルへ戻り、DATAの読み込み動作を繰り返します。

(43)DATA = [H]
すべてのDATAがDDSへ送り終えたら、DATA信号ラインを「H」に設定しておきます。

(44)ポートの誤動作防止
ここは、(43)と(45)のように、BSF,BCFなどのビット操作命令を使って、同じポートに出力する場合には、間にダミーとしてNOP命令などを入れる。(38)参照

(45)STB = [L]
DDSへのSTB信号ラインを[L]にします。このとき、STBの立ち下がりで、読み込まれたコマンド・データが実行され、DDSの出力端子から10MHzの信号が出力されます。

(46)ポートの誤動作防止
ここは、(45)と(47)のように、BSF,BCFなどのビット操作命令を使って、同じポートに出力する場合には、間にダミーとしてNOP命令などを入れる。(38)参照

(47)STB = [H]
STB信号ラインを「H」に設定して終了します。

(48)繰り返しデータ受信動作に入る
DDSの設定が終了した後、PIC側の動作としては、次の新たな設定データが受信されるのを待ちます。

(49)DATA = [L]
(36)の分岐命令で、1ビット分の読み込まれたデータが、0だったらDDSへのDATA信号ラインを[L]にするルーチン。

(50)DATA = [H]
(36)の分岐命令で、1ビット分の読み込まれたデータが、1だったらDDSへのDATA信号ラインを[H]にするルーチン。

(51)TABLEの定義(PC+OFFSET相当のシフトカウンタ値を持って戻る)
    PC+OFFSET

データテーブルのサブルーチンに来ると、プログラムカウンタに、Wregの値(オフセット)が加算されます。その加算結果をプログラムカウンタとしますので、そのデータカウンタ(アドレス)で指定された値を示すようになります。

ADDWF   PCL,F ;プログラムカウンタに、Wregの値(オフセット)を加算し、
             その加算結果をプログラムカウンタする。

(52)ダミーデータ
データカウンタの値は、シフトカウンタ値が記載されたテーブルの位置関係を指し示します。データカウンタ(アドレス)で指定された値の位置関係を対応させるために、ここにダミーを入れておきます。
(注)(42)の分岐命令により、データカウンタが0のときデータの読み込みルーチンを抜けてしまうため、ここのアドレス位置にデータを記載しても読み込みがされませんのでNOPとしています。

(53)各データに対するシフトカウンタ値
表3に各DDS設定データに対するシフトカウンタ値を示します。
まずチップセレクト&コマンドデータですが、チップセレクト端子は、CS2、CS1、CS0の3ビットで構成され、コマンドデータは、4ビットですので、合計で7ビット分になります。次に周波数データですが、Lower Byteは 0ビット目〜7ビット目までの8ビット分、Middle Byteは 8ビット目〜15ビット目までの8ビット分、Higher Byteは 16ビット目〜23ビット目までの8ビット分、さらに、24,25ビット目で2ビット分というように、シフトカウンタ値を設定します。

表3.各DDS設定データに対するシフトカウンタ値
データの項目 シフトカウンタ値
チップセレクト&コマンドデータ
周波数データ(Lower Byte: 0ビット目〜7ビット目)
周波数データ(Middle Byte: 8ビット目〜15ビット目)
周波数データ(Higher Byte: 16ビット目〜23ビット目)
周波数データ(24,25ビット目 ビットの値は常に0)


(54)<フレーミングエラー時の処理>
    00001111 を Wreg にロードする,PORTBへWregのデータを出力
    (LEDの点灯状態でエラーを知らせる)

ここでは、フレーミングエラーが発生したことを確認するため、 PORTB 下位4ビットの LED を点灯させるようにします。

(55)1秒のウエイトを入れる
PORTB の LED の点灯時間を1秒間に設定します。ここでは、遅延サブルーチンを使っています。

(56)00000000 を Wreg にロードし、
    PORTBへWregのデータを出力(LEDの消灯)
点灯していたLEDを消灯させます。

(57)ダミーの入力(RCREGをリードするとFERRがクリアされる)ここがポイント
<フレーミングエラー時の処理>
受信時にフレーミングエラーが発生した場合、フレーミングエラービットFREEが「1」となっています。
フレーミングエラービットをリセットする場合には、RCREGレジスタ(USART受信レジスタ)をWregにロードするというダミー命令を実行します。

(58)オーバーランエラーのチェック(1:エラー,0:正常)
    オーバーランエラーがなければ MAIN のラベルへジャンプする

受信ステータスおよびコントロールレジスタであるRCSTAレジスタのオーバーランエラービット(OERR)の状態をチェックします。
BTFSS   RCSTA,OERR
「RCSTA」レジスタのOERRビットがエラーの「1」だったら次の命令をスキップし、オーバーランエラーのチェックへ進みます。
GOTO   MAIN
オーバーランエラーがなければMAINのラベルへジャンプし、受信を最初からやり直します。

(59)<オーバーランエラー時の処理>
    11110000 を Wreg にロードする,PORTBへWregのデータを出力
    (LEDの点灯状態でエラーを知らせる)

ここでは、オーバーランエラーが発生したことを確認するため、 PORTB 上位4ビットの LED を点灯させるようにします。

(60)1秒のウエイトを入れる
PORTB の LED の点灯時間を1秒間に設定します。ここでは、遅延サブルーチンを使っています。

(61)00000000 を Wreg にロードし、
    PORTBへWregのデータを出力(LEDの消灯)
点灯していたLEDを消灯させます。

(62)OERRのリセット(ビットCREN のクリアによりクリアする)ここがポイント
<オーバーランエラー時の処理>

受信時にオーバーランエラーが発生した場合、オーバーランエラービットOERRが「1」となっています。
オーバーランエラービットをリセットする場合には、RCSTAレジスタ(受信ステータスおよびコントロールレジスタ)の連続受信イネーブルビット(CREN)をクリアすることにより、オーバーランエラービット(OERR)がクリアされます。

(63)連続受信を許可する
先のオーバーランエラー時の処理で連続受信イネーブルビット(CREN)がクリアされてしまっているので、元の「1」にセットして戻しておきます。

(64)MAIN のラベルへジャンプする
MAINのラベルへジャンプし、受信を最初からやり直します。


<項目>DDSの動作確認
それでは、パソコンからシリアル通信ソフト「Acknowrich」を使って、DDSをコントロールしてみましょう。Acknowrichからのデータ転送は、バイナリモードで行います。
図4は、Acknowrichを使ったDDSの設定データを示しています。そのときのDDSの出力波形(図5)をオシロスコープで見たところです。3画像とも比較のため、タイムレンジは同じにしています。これらの結果から、パソコンからDDSを制御できることが確認できました。

Acknowrichを使ったDDSの設定(コマンドC,f=1MHz設定) Acknowrichを使ったDDSの設定(コマンドC,f=2MHz設定) Acknowrichを使ったDDSの設定(コマンドC,f=10MHz設定)
(1)コマンドC
f=1MHz設定
(2)コマンドC
f=2MHz設定
(3)コマンドC
f=10MHz設定
図4.Acknowrichを使ったDDSの設定
DDSの出力波形(f=1MHz設定) DDSの出力波形(f=2MHz設定) DDSの出力波形(f=10MHz設定)
(1)f=1MHz設定 (2)f=2MHz設定 (3)f=10MHz設定
図4.DDSの出力波形


このようにして、パソコンからDDSキットを制御できることがわかりました。しかし、シリアル通信ソフト「Acknowrich」からDDSの設定データを入力するのは何かと不便です。そこで、「次へ」は専用のDDS制御ソフトをVisualBasicで開発していくことにします。



<前ページへ> <次ページへ>
<TOPページへ>



PC用眼鏡【管理人も使ってますがマジで疲れません】 解約手数料0円【あしたでんき】 Yahoo 楽天 NTT-X Store

無料ホームページ 無料のクレジットカード 海外格安航空券 ふるさと納税 海外旅行保険が無料! 海外ホテル